package com.baidu.dtx.coupon.service.impl;

import com.baidu.dtx.common.enums.TccEnum;
import com.baidu.dtx.coupon.dto.CouponDTO;
import com.baidu.dtx.coupon.entities.CouponConsume;
import com.baidu.dtx.coupon.entities.CouponReceive;
import com.baidu.dtx.coupon.mapper.CouponConsumeMapper;
import com.baidu.dtx.coupon.mapper.CouponReceiveMapper;
import com.baidu.dtx.coupon.service.CouponService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author shilei
 * @create 2021-06-07 16:30
 */
@Service
@Slf4j
public class CouponServiceImpl implements CouponService
{
    @Resource
    private CouponReceiveMapper couponReceiveMapper;
    @Resource
    private CouponConsumeMapper couponConsumeMapper;

    @Hmily(confirmMethod = "confirmMethod",cancelMethod = "cancelMethod")
    @Transactional
    public  void decrease(CouponDTO couponDTO){
        log.info("-------进入优惠卷的try-------");
        //第一步:检验优惠卷合法有效
        CouponReceive couponReceive=new CouponReceive();
        couponReceive.setId(couponDTO.getCouponId());
        couponReceive=this.couponReceiveMapper.selectOne(couponReceive);
        if(couponReceive==null || couponReceive.getStatus() != 1){
            throw new RuntimeException("未查到优惠卷");
        }

        //第二步：幂等性校验没有被消费过
        CouponConsume couponConsume=new CouponConsume();
        couponConsume.setOrderNo(couponDTO.getOrderNo());
        couponConsume.setCouponReceiveId(couponDTO.getCouponId());
        couponConsume.setDeleted((byte)0);
        if(this.couponConsumeMapper.selectOne(couponConsume)!=null){
            throw new RuntimeException("存在订单号！");
        }

        //第三步：插入消费表，消费卷下发后都是在顾客自己身上，不用冻结这样的操作
        BeanUtils.copyProperties(couponDTO,couponConsume);
        couponConsume.setTxStatus(TccEnum.TRY.getCode());
        this.couponConsumeMapper.insertSelective(couponConsume);
    }

    @Transactional
    public void confirmMethod(CouponDTO couponDTO){
        log.info("-------进入优惠卷的confirm-------");
        //第一步：幂等性校验
        CouponConsume couponConsume=new CouponConsume();
        couponConsume.setOrderNo(couponDTO.getOrderNo());
        couponConsume.setCouponReceiveId(couponDTO.getCouponId());
        couponConsume=this.couponConsumeMapper.selectOne(couponConsume);
        if(couponConsume.getTxStatus()==TccEnum.CONFIRM.getCode()){
            throw new RuntimeException("该订单号，已经confirm!");
        }
        //第二步：修改订单明细状态，作用：幂等性校验
        CouponConsume updateCouponConsume=new CouponConsume();
        updateCouponConsume.setId(couponConsume.getId());
        updateCouponConsume.setTxStatus(TccEnum.CONFIRM.getCode());
        this.couponConsumeMapper.updateByPrimaryKeySelective(updateCouponConsume);
        //第三步：该领取表
        CouponReceive couponReceive=new CouponReceive();
        couponReceive.setId(couponDTO.getCouponId());
        couponReceive.setStatus((byte)2);//2为已使用
        this.couponReceiveMapper.updateByPrimaryKeySelective(couponReceive);
        //故意模拟优惠券confirm阶段出错，tcc2库里面的hmily_dtx_coupon3001表有记录
        // 后续修复bug后，再从起本微服务，让它自行完成修复。
        int i = 11/0;
    }

    @Transactional
    public  void cancelMethod(CouponDTO couponDTO){
        log.info("-------进入优惠卷的cancel-------");
        //第一步：幂等性校验
        CouponConsume couponConsume=new CouponConsume();
        couponConsume.setOrderNo(couponDTO.getOrderNo());
        couponConsume.setCouponReceiveId(couponDTO.getCouponId());
        couponConsume=this.couponConsumeMapper.selectOne(couponConsume);
        if(couponConsume.getTxStatus()==TccEnum.CANCEL.getCode()){
            throw new RuntimeException("该订单号，已经cancel!");
        }

        //第二步：删除消费表，并且设置事务状态为cancel
        CouponConsume updateCouponConsume=new CouponConsume();
        updateCouponConsume.setId(couponConsume.getId());
        updateCouponConsume.setTxStatus(TccEnum.CANCEL.getCode());
        updateCouponConsume.setDeleted((byte)1);
        this.couponConsumeMapper.updateByPrimaryKeySelective(updateCouponConsume);
    }
}
